package com.telit.common.util;

import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;


@Component
public class LongitudeLatitudeTransisteUtils {

    private static final double pi = 3.1415926535897932384626;
    private static final double x_pi = 3.14159265358979324 * 3000.0 / 180.0;
    private static final double a = 6378245.0;
    private static final double ee = 0.00669342162296594323;

    /**
     * 转换纬度
     * @param longitude
     * @param latitude
     * @return
     */
    public static double transformLatitude(double longitude,double latitude){
        double result = -100.0 + 2.0 * longitude + 3.0 * latitude + 0.2 * latitude * latitude + 0.1 * longitude * latitude + 0.2 * Math.sqrt(Math.abs(longitude));
        result += (20.0 * Math.sin(6.0 * longitude * pi) + 20.0 * Math.sin(2.0 * longitude * pi)) * 2.0 / 3.0;
        result += (20.0 * Math.sin(latitude * pi) + 40.0 * Math.sin(latitude / 3.0 * pi)) * 2.0 / 3.0;
        result += (160.0 * Math.sin(latitude / 12.0 * pi) + 320 * Math.sin(latitude * pi / 30.0)) * 2.0 / 3.0;
        return result;
    }

    /**
     * 转换经度
     * @param longitude
     * @param latitude
     * @return
     */
    public static double transformLongitude(double longitude,double latitude){
        double ret = 300.0 + longitude + 2.0 * latitude + 0.1 * longitude * longitude + 0.1 * longitude * latitude + 0.1 * Math.sqrt(Math.abs(longitude));
        ret += (20.0 * Math.sin(6.0 * longitude * pi) + 20.0 * Math.sin(2.0 * longitude * pi)) * 2.0 / 3.0;
        ret += (20.0 * Math.sin(longitude * pi) + 40.0 * Math.sin(longitude / 3.0 * pi)) * 2.0 / 3.0;
        ret += (150.0 * Math.sin(longitude / 12.0 * pi) + 300.0 * Math.sin(longitude / 30.0 * pi)) * 2.0 / 3.0;
        return ret;
    }

    /**
     * 转换经纬度
     * @param longitude
     * @param latitude
     * @return
     */
    public static double[] transform(double longitude, double latitude) {
        if (outOfChina(latitude, longitude)) {
            return new double[]{latitude,longitude};
        }
        double dLat = transformLatitude(longitude - 105.0, latitude - 35.0);
        double dLon = transformLongitude(longitude - 105.0, latitude - 35.0);
        double radLat = latitude / 180.0 * pi;
        double magic = Math.sin(radLat);
        magic = 1 - ee * magic * magic;
        double sqrtMagic = Math.sqrt(magic);
        dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * pi);
        dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * pi);
        double mgLat = latitude + dLat;
        double mgLon = longitude + dLon;
        return new double[]{mgLat,mgLon};
    }

    /**
     * 判断是否在中国
     * @param longitude
     * @param latitude
     * @return
     */
    public static boolean outOfChina(double longitude, double latitude) {
        if (longitude < 72.004 || longitude > 137.8347)
            return true;
        if (latitude < 0.8293 || latitude > 55.8271)
            return true;
        return false;
    }

    /**
     * 84 ==》 高德
     * @param longitude
     * @param latitude
     * @return
     */
    public static double[] gps84_To_Gcj02(double longitude, double latitude) {
        if (outOfChina(longitude, latitude)) {
            return new double[]{longitude,latitude};
        }
        double dLat = transformLatitude(longitude - 105.0, latitude - 35.0);
        double dLon = transformLongitude(longitude - 105.0, latitude - 35.0);
        double radLat = latitude / 180.0 * pi;
        double magic = Math.sin(radLat);
        magic = 1 - ee * magic * magic;
        double sqrtMagic = Math.sqrt(magic);
        dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * pi);
        dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * pi);
        double mgLat = latitude + dLat;
        double mgLon = longitude + dLon;
        return new double[]{mgLon,mgLat};
    }

    /**
     * 高德 ==》 84
     * @param longitude
     * @param latitude
     * @return
     */
    public static double[] gcj02_To_Gps84(double longitude, double latitude) {
        double[] gps = transform(longitude, latitude);
        double retLongitude = longitude * 2 - gps[1];
        double retLatitude = latitude * 2 - gps[0];
        //纬度,经度
        return new double[]{retLongitude, retLatitude};
    }

    /**
     * 高德 == 》 百度
     * @param longitude
     * @param latitude
     * @return
     */
    public static double[] gcj02_To_Bd09(double longitude, double latitude) {
        double x = longitude, y = latitude;
        double z = Math.sqrt(x * x + y * y) + 0.00002 * Math.sin(y * x_pi);
        double theta = Math.atan2(y, x) + 0.000003 * Math.cos(x * x_pi);
        double tempLon = z * Math.cos(theta) + 0.0065;
        double tempLat = z * Math.sin(theta) + 0.006;
        double[] gps = {tempLon,tempLat};
        return gps;
    }

    /**
     * 百度 == 》 高德
     * @param longitude
     * @param latitude
     * @return
     */
    public static double[] bd09_To_Gcj02(double longitude, double latitude) {
        double x = longitude - 0.0065, y = latitude - 0.006;
        double z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * x_pi);
        double theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * x_pi);
        double tempLon = z * Math.cos(theta);
        double tempLat = z * Math.sin(theta);
        //纬度 经度
        double[] gps = {tempLon,tempLat};
        return gps;
    }

    /**
     * 84 == 》 百度 
     * @param longitude
     * @param latitude
     * @return
     */
    public static double[] gps84_To_bd09(double longitude, double latitude){
        double[] gcj02 = gps84_To_Gcj02(longitude,latitude);
        double[] bd09 = gcj02_To_Bd09(gcj02[0],gcj02[1]);
        return bd09;
    }

    public static void main(String[] args) {
        double[] doubles = gps84_To_Gcj02(118.391081, 32.055455);
        for (double aDouble : doubles) {
            System.out.println(aDouble);
        }
    }

    /**
     * 百度 == 》 84
     * @param longitude
     * @param latitude
     * @return
     */
    public static double[] bd09_To_gps84(double longitude, double latitude){
        //纬度,经度
        double[] gcj02 = bd09_To_Gcj02(longitude, latitude);
        //纬度,经度
        double[] gps84 = gcj02_To_Gps84(gcj02[0], gcj02[1]);
        //保留小数点后六位  
        gps84[0] = retain6(gps84[0]);
        gps84[1] = retain6(gps84[1]);
        return gps84;
    }

    public static List<double[]> bd09_To_gps84Array(ArrayList<double[]> doubles){
        List<double[]> resultList = new ArrayList<>();
        doubles.forEach(doubles1 -> {
            //传参 纬度,经度  结果纬度,经度
            double[] gcj02 = bd09_To_Gcj02(doubles1[0], doubles1[1]);
            //传参纬度,经度  结果纬度 经度;
            double[] gps84 = gcj02_To_Gps84(gcj02[0], gcj02[1]);
            //保留小数点后六位
            //纬度 经度
            /*gps84[0] = retain6(gps84[0]);

            gps84[1] = retain6(gps84[1]);*/

            double[] result = new double[2] ;
            //经度
            result[0] =  retain6(gps84[0]);
            //纬度
            result[1] =  retain6(gps84[1]);

            resultList.add(result);
        });

        return resultList;
    }

    /*
     * 保留小数点后六位
     * @param num
     * @return
     */
    private static double retain6(double num){
        String result = String .format("%.6f", num);
        return Double.valueOf(result);
    }
}
